package pres.man.interview.producerconsumer.smoker;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 吸烟者问题
 *
 * @author MAN
 * @date 2020-12-07 21:33
 * @project
 * @since
 */
public class Smoker {
    private static final ThreadPoolExecutor POOL = new ThreadPoolExecutor(5, 8, 20, TimeUnit.SECONDS, new ArrayBlockingQueue<>(10), new ThreadPoolExecutor.CallerRunsPolicy());

    public static void main(String[] args) {
        Smoker smoker = new Smoker();

        // TODO 抽烟者的顺序有点乱序

        POOL.execute(() -> {
            for (; ; ) {
                smoker.provider();
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        POOL.execute(() -> {
            for (; ; ) {
                smoker.smoker1();
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        POOL.execute(() -> {
            for (; ; ) {
                smoker.smoker2();
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        POOL.execute(() -> {
            for (; ; ) {
                smoker.smoker3();
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
    }


    private static final Semaphore SET_MEAL_1 = new Semaphore(0);
    private static final Semaphore SET_MEAL_2 = new Semaphore(0);
    private static final Semaphore SET_MEAL_3 = new Semaphore(0);
    private static final Semaphore FINISH = new Semaphore(0);

    private static final Lock LOCK = new ReentrantLock();


    public void smoker1() {
        LOCK.lock();
        try {
            SET_MEAL_1.acquire();
            System.out.println("第一号抽烟");
            SET_MEAL_1.release();
            FINISH.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            LOCK.unlock();
        }
    }

    public void smoker2() {
        LOCK.lock();
        try {
            SET_MEAL_2.acquire();
            System.out.println("第二号抽烟");
            SET_MEAL_2.release();
            FINISH.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            LOCK.unlock();
        }
    }

    public void smoker3() {
        LOCK.lock();
        try {
            SET_MEAL_3.acquire();
            System.out.println("第三号抽烟");
            SET_MEAL_3.release();
            FINISH.release();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            LOCK.unlock();
        }
    }

    public void provider() {
        for (int i = 0; ; i++) {
            try {
                TimeUnit.SECONDS.sleep(2);
                if (i % 3 == 0) {
                    System.out.println("提供一套餐");
                    SET_MEAL_1.release();
                }
                if (i % 3 == 1) {
                    System.out.println("提供二套餐");
                    SET_MEAL_2.release();
                }
                if (i % 3 == 2) {
                    System.out.println("提供三套餐");
                    SET_MEAL_3.release();
                }
                FINISH.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
            }
        }
    }
}
